﻿using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using Shipeng.Util.Cache;
using System.Linq.Expressions;
using System.Reflection;

namespace YNTK.Data.MongoDB.Repositorie
{
    /// <summary>
    /// MongoDB仓储实现类
    /// </summary>
    public partial class MongoDBRepository<TEntity> : IMongoDBRepository<TEntity>
    where TEntity : class, new()
    {
        private readonly YNTKDbMongoDBContext _yNTKDbMongoDBContext;//mongodb上下文
        private readonly IMongoDatabase db;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="yNTKDbMongoDBContext"></param>
        public MongoDBRepository(YNTKDbMongoDBContext yNTKDbMongoDBContext)
        {
            _yNTKDbMongoDBContext = yNTKDbMongoDBContext;
            //从MongoDB上下文获取或者创建放置对应信息的库(sql中的库)
            //数据库不存在，也没有关系，它会在首次使用数据库的时候进行自动创建
            db = _yNTKDbMongoDBContext.Database;
        }

        /// <summary>
        /// 检查表是否存在
        /// </summary>
        /// <param name="collectionName">数据集</param>
        /// <returns></returns>
        public bool Exists(string collectionName)
        {
            var options = new ListCollectionsOptions
            {
                Filter = Builders<BsonDocument>.Filter.Eq("name", collectionName)
            };
            return db.ListCollections(options).ToEnumerable().Any();
        }

        /// <summary>
        /// 检查表是否存在
        /// </summary>
        /// <param name="collectionName">数据集</param>
        /// <returns></returns>
        public async Task<bool> ExistsAsync(string collectionName)
        {
            var options = new ListCollectionsOptions
            {
                Filter = Builders<BsonDocument>.Filter.Eq("name", collectionName)
            };
            return (await db.ListCollectionsAsync(options)).ToEnumerable().Any();
        }

        /// <summary>  
        /// 创建索引   
        /// </summary>  
        public bool CreateIndex()
        {
            try
            {
                string collectionName = typeof(TEntity).Name;
                MongoCollection<BsonDocument> mc = 
                    (MongoCollection<BsonDocument>)db.GetCollection<BsonDocument>(collectionName);

                PropertyInfo[] propertys = typeof(TEntity).GetProperties(BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty);
                //得到该实体类型的属性  
                foreach (PropertyInfo property in propertys)
                {
                    //在各个属性中得到其特性  
                    foreach (object obj in property.GetCustomAttributes(true))
                    {
                        MongoDbFieldAttribute? mongoField = obj as MongoDbFieldAttribute;
                        if (mongoField != null)
                        {// 此特性为mongodb的字段属性  
                            IndexKeysBuilder indexKey;
                            if (mongoField.Ascending)
                            {
                                //升序 索引  
                                indexKey = IndexKeys.Ascending(property.Name);
                            }
                            else
                            {
                                //降序索引  
                                indexKey = IndexKeys.Descending(property.Name);
                            }
                            //创建该属性  
                            mc.CreateIndex(indexKey, IndexOptions.SetUnique(mongoField.Unique));
                        }
                    }
                }
                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 添加一条数据
        /// </summary>
        /// <param name="entity">添加的实体</param>
        /// <param name="name">数据集</param>
        /// <returns></returns>
        public bool Add(TEntity entity,string name)
        {
            try
            {
                /* 获取或者创建线路跟踪集合
                 * 2、我们可以调用database的GetCollection<TDocument> 方法来获取数据集，(sql中的表)
                 * 2-1其中如果数据是预先定义好的可以在<输入数据的类型>  ,如果是没有定义好的，
                 * 可以使用BsonDocument类型，BsonDocument表示没有预定于的模式。
                 * 2-2我们将获取到上面“db”所对应的数据库中的“freight_line”集合，
                 * 即使“freight_line”集合不存在也没有关系，
                 * 同数据库一样，若数据集不存在，会自动创建该数据集。
                 */
                var client = db.GetCollection<TEntity>(name);
                client.InsertOne(entity);
                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 异步添加一条数据
        /// </summary>
        /// <param name="entity">添加的实体</param>
        /// <param name="name">数据集</param>
        /// <returns></returns>
        public async Task<bool> AddAsync(TEntity entity, string name)
        {
            try
            {
                foreach (var item in entity.GetType().GetProperties())
                {
                    if ((item.PropertyType == typeof(DateTime) || item.PropertyType == typeof(DateTime?))
                        && item.GetValue(entity) != null)
                    {
                        //mongodb插入日期格式的数据时发现，日期时间相差8个小时，
                        //原来存储在mongodb中的时间是标准时间UTC +0:00，而中国的时区是+8.00
                        //因此在插入的时候需要对时间进行处理：
                        //DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc);
                        item.SetValue(entity, DateTime.SpecifyKind((DateTime)item.GetValue(entity), DateTimeKind.Utc));
                    }
                }
                var client = db.GetCollection<TEntity>(name);
                await client.InsertOneAsync(entity);
                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>  
        /// 将数据插入进数据库  
        /// </summary>  
        /// <param name="entity">需要插入数据库的具体实体</param>  
        /// <param name="name">指定插入的集合</param>  
        public bool Insert(TEntity entity, string name)
        {
            try
            {
                MongoCollection<BsonDocument> mc = 
                    (MongoCollection<BsonDocument>)db.GetCollection<BsonDocument>(name);
                //将实体转换为bson文档  
                BsonDocument bd = entity.ToBsonDocument();
                //进行插入操作  
                WriteConcernResult result = mc.Insert(bd);
                if (!string.IsNullOrEmpty(result.LastErrorMessage))
                {
                    return false;
                }
                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 批量插入
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <param name="name">数据集</param>
        /// <returns></returns>
        public bool AddList(List<TEntity> entities, string name)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                client.InsertMany(entities);
                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 异步批量插入
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <param name="name">数据集</param>
        /// <returns></returns>
        public async Task<bool> AddListAsync(List<TEntity> entities, string name)
        {
            try
            {
                if (!entities.Any()) return false;
                foreach (TEntity entity in entities)
                {
                    foreach (var item in entity.GetType().GetProperties())
                    {
                        if ((item.PropertyType == typeof(DateTime) || item.PropertyType == typeof(DateTime?))
                         && item.GetValue(entity) != null)
                        {
                            //mongodb插入日期格式的数据时发现，日期时间相差8个小时，
                            //原来存储在mongodb中的时间是标准时间UTC +0:00，而中国的时区是+8.00
                            //因此在插入的时候需要对时间进行处理：
                            //DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc);
                            item.SetValue(entity, DateTime.SpecifyKind((DateTime)item.GetValue(entity), DateTimeKind.Utc));
                        }
                    }
                }
                var client = db.GetCollection<TEntity>(name);
                await client.InsertManyAsync(entities);
                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>  
        /// 批量插入数据  
        /// </summary>  
        /// <param name="list">需要插入数据的列表</param>  
        /// <param name="name">指定要插入的集合</param>  
        public bool InsertBatch(List<TEntity> list, string name)
        {
            try
            {
                MongoCollection<BsonDocument> mc = 
                    (MongoCollection<BsonDocument>)db.GetCollection<BsonDocument>(name);
                //创建一个空间bson集合  
                List<BsonDocument> bsonList = new List<BsonDocument>();
                //批量将数据转为bson格式 并且放进bson文档  
                list.ForEach(t => bsonList.Add(t.ToBsonDocument()));
                //批量插入数据  
                mc.InsertBatch(bsonList);
                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 修改一条数据
        /// </summary>
        /// <param name="entity">添加的实体</param>
        /// <param name="name">数据集</param>
        /// <param name="id"></param>
        /// <returns></returns>
        public UpdateResult Update(TEntity entity, string name, string id)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                //修改条件
                FilterDefinition<TEntity> filter = Builders<TEntity>.Filter.Eq("_id", new ObjectId(id));
                //要修改的字段
                var list = new List<UpdateDefinition<TEntity>>();
                foreach (var item in entity.GetType().GetProperties())
                {
                    if (item.Name.ToLower() == "id") continue;
                    list.Add(Builders<TEntity>.Update.Set(item.Name, item.GetValue(entity)));
                }
                var updatefilter = Builders<TEntity>.Update.Combine(list);
                return client.UpdateOne(filter, updatefilter);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 异步修改一条数据
        /// </summary>
        /// <param name="entity">添加的实体</param>
        /// <param name="name">数据集</param>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<UpdateResult> UpdateAsync(TEntity entity, string name, string id)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                //修改条件
                FilterDefinition<TEntity> filter = Builders<TEntity>.Filter.Eq("_id", new ObjectId(id));
                //要修改的字段
                var list = new List<UpdateDefinition<TEntity>>();
                foreach (var item in entity.GetType().GetProperties())
                {
                    if (item.Name.ToLower() == "id") continue;
                    list.Add(Builders<TEntity>.Update.Set(item.Name, item.GetValue(entity)));
                }
                var updatefilter = Builders<TEntity>.Update.Combine(list);
                return await client.UpdateOneAsync(filter, updatefilter);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 异步修改一条数据
        /// </summary>
        /// <param name="entity">添加的实体</param>
        /// <param name="name">数据集</param>
        /// <param name="filter">条件</param>
        /// <returns></returns>
        public async Task<UpdateResult> UpdateAsync(TEntity entity, string name,
            Expression<Func<TEntity, bool>> filter)
        {
            try
            {
                //数据表不存在添加
                if (!await ExistsAsync(name)) await AddAsync(entity,name);
                //当前记录不存在添加
                if((await GetAsync(name,filter))==null) await AddAsync(entity, name);
                var client = db.GetCollection<TEntity>(name);
                //要修改的字段
                var list = new List<UpdateDefinition<TEntity>>();
                object? value = null;
                foreach (var item in entity.GetType().GetProperties())
                {
                    if (item.Name.ToLower() == "id") continue;
                    value = item.GetValue(entity);
                    if ((item.PropertyType == typeof(DateTime) || item.PropertyType == typeof(DateTime?))
                        && value != null)
                    {
                        //mongodb插入日期格式的数据时发现，日期时间相差8个小时，
                        //原来存储在mongodb中的时间是标准时间UTC +0:00，而中国的时区是+8.00
                        //因此在插入的时候需要对时间进行处理：
                        //DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc);
                        value = DateTime.SpecifyKind((DateTime)value, DateTimeKind.Utc);
                    }
                    list.Add(Builders<TEntity>.Update.Set(item.Name, value));
                }
                var updatefilter = Builders<TEntity>.Update.Combine(list);
                return await client.UpdateOneAsync(filter, updatefilter);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 替换单个文档
        /// </summary>
        /// <param name="entity">添加的实体</param>
        /// <param name="name">数据集</param>
        /// <param name="filter">条件</param>
        /// <returns></returns>
        public async Task<ReplaceOneResult> ReplaceOneAsync(TEntity entity, string name,
            Expression<Func<TEntity, bool>> filter)
        {
            try
            {
                //数据表不存在添加
                if (!await ExistsAsync(name)) await AddAsync(entity, name);
                //当前记录不存在添加
                if ((await GetAsync(name, filter)) == null) await AddAsync(entity, name);
                var client = db.GetCollection<TEntity>(name);
                return await client.ReplaceOneAsync(filter, entity);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>  
        /// 更新数据  
        /// </summary>  
        /// <param name="query">更新数据的查询</param>  
        /// <param name="update">需要更新的文档</param>  
        /// <param name="name">指定更新集合的名称</param>  
        /// <param name="id">ObjectId的键</param>
        public bool Update(IMongoQuery query, IMongoUpdate update, string name, string id)
        {
            try
            {
                MongoCollection<TEntity> mc = 
                    (MongoCollection<TEntity>)db.GetCollection<TEntity>(name);
                query = InitQuery(query, id);
                //更新数据  
                WriteConcernResult result = mc.Update(query, update, UpdateFlags.Multi);
                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 批量修改数据
        /// </summary>
        /// <param name="dic">要修改的字段</param>
        /// <param name="name">数据集</param>
        /// <param name="filter">修改条件</param>
        /// <returns></returns>
        public UpdateResult UpdateManay(Dictionary<string, string> dic, string name, FilterDefinition<TEntity> filter)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                TEntity entity = new TEntity();
                //要修改的字段
                var list = new List<UpdateDefinition<TEntity>>();
                foreach (var item in entity.GetType().GetProperties())
                {
                    if (!dic.ContainsKey(item.Name)) continue;
                    var value = dic[item.Name];
                    list.Add(Builders<TEntity>.Update.Set(item.Name, value));
                }
                var updatefilter = Builders<TEntity>.Update.Combine(list);
                return client.UpdateMany(filter, updatefilter);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 异步批量修改数据
        /// </summary>
        /// <param name="dic">要修改的字段</param>
        /// <param name="name">数据集</param>
        /// <param name="filter">修改条件</param>
        /// <returns></returns>
        public async Task<UpdateResult> UpdateManayAsync(Dictionary<string, string> dic, string name, FilterDefinition<TEntity> filter)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                TEntity entity = new TEntity();
                //要修改的字段
                var list = new List<UpdateDefinition<TEntity>>();
                foreach (var item in entity.GetType().GetProperties())
                {
                    if (!dic.ContainsKey(item.Name)) continue;
                    var value = dic[item.Name];
                    list.Add(Builders<TEntity>.Update.Set(item.Name, value));
                }
                var updatefilter = Builders<TEntity>.Update.Combine(list);
                return await client.UpdateManyAsync(filter, updatefilter);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 批量修改数据
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <param name="name">数据集</param>
        /// <returns></returns>
        public async Task<int> UpdateManayAsync(List<TEntity> entities, string name)
        {
            try
            {
                int result = 0;
                if (!await ExistsAsync(name))
                {
                    if (await AddListAsync(entities, name)) return entities.Count();
                }
                var client = db.GetCollection<TEntity>(name);
                //要修改的字段
                var list = new List<UpdateDefinition<TEntity>>();
                UpdateResult update;
                var id="";
                object? value = null;
                foreach (TEntity entity in entities)
                {                   
                    list = new List<UpdateDefinition<TEntity>>();
                    foreach (var item in entity.GetType().GetProperties())
                    {                     
                        if (item.Name.ToLower() == "id")
                        {
                            id = item.GetValue(entity).ToString();
                            continue;
                        }
                        value = item.GetValue(entity);
                        if ((item.PropertyType == typeof(DateTime) || item.PropertyType == typeof(DateTime?))
                        && value != null)
                        {
                            //mongodb插入日期格式的数据时发现，日期时间相差8个小时，
                            //原来存储在mongodb中的时间是标准时间UTC +0:00，而中国的时区是+8.00
                            //因此在插入的时候需要对时间进行处理：
                            //DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc);
                            value = DateTime.SpecifyKind((DateTime)value, DateTimeKind.Utc);
                        }
                        list.Add(Builders<TEntity>.Update.Set(item.Name, value));                 
                    }
                    UpdateDefinition<TEntity> updatefilter = Builders<TEntity>.Update.Combine(list);
                    var filter = Builders<TEntity>.Filter.Eq("_id", id);
                    update =await client.UpdateManyAsync(filter, updatefilter);
                    if (update.ModifiedCount > 0) result++;
                }
                return result;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 删除一条数据
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="id">objectId</param>
        /// <returns></returns>
        public DeleteResult Delete(string name, string id)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                FilterDefinition<TEntity> filter = Builders<TEntity>.Filter.Eq("_id", new ObjectId(id));
                return client.DeleteOne(filter);
            }
            catch (Exception)
            {
                throw;
            }

        }

        /// <summary>
        /// 异步删除一条数据
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="id">objectId</param>
        /// <returns></returns>
        public async Task<DeleteResult> DeleteAsync(string name, string id)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                //修改条件
                FilterDefinition<TEntity> filter = Builders<TEntity>.Filter.Eq("_id", new ObjectId(id));
                return await client.DeleteOneAsync(filter);
            }
            catch (Exception)
            {
                throw;
            }

        }

        /// <summary>  
        /// 移除指定的数据  
        /// </summary>  
        /// <param name="query">移除的数据条件</param>  
        /// <param name="name">指定的集合名词</param>  
        public bool Remove(IMongoQuery query, string name)
        {
            try
            {
                MongoCollection<TEntity> mc =
                    (MongoCollection<TEntity>)db.GetCollection<TEntity>(name);
                query = InitQuery(query,"");
                //根据指定查询移除数据  
                mc.Remove(query);
                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 删除多条数据
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="filter">删除的条件</param>
        /// <returns></returns>
        public DeleteResult DeleteMany(string name, FilterDefinition<TEntity> filter)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                return client.DeleteMany(filter);
            }
            catch (Exception)
            {
                throw;
            }

        }

        /// <summary>
        /// 根据条件删除数据
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="where">删除的条件</param>
        /// <returns></returns>
        public long Delete(string name, Expression<Func<TEntity, bool>> where)
        {
            try
            {
                if (!Exists(name)) return 1;
                var client = db.GetCollection<TEntity>(name);
                return client.DeleteMany(where).DeletedCount;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 异步删除多条数据
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="filter">删除的条件</param>
        /// <returns></returns>
        public async Task<DeleteResult> DeleteManyAsync(string name, FilterDefinition<TEntity> filter)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                return await client.DeleteManyAsync(filter);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 异步删除多条数据
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="where">删除的条件</param>
        /// <returns></returns>
        public async Task<long> DeleteAsync(string name, Expression<Func<TEntity, bool>> where)
        {
            try
            {
                if (!await ExistsAsync(name)) return 1;
                var client = db.GetCollection<TEntity>(name);
                return (await client.DeleteManyAsync(where)).DeletedCount;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 根据id查询一条数据
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="id">objectid</param>
        /// <param name="field">要查询的字段，不写时查询全部</param>
        /// <returns></returns>
        public TEntity Get(string name, string id, string[]? field = null)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                FilterDefinition<TEntity> filter = Builders<TEntity>.Filter.Eq("_id", new ObjectId(id));
                //不指定查询字段
                if (field == null || field.Length == 0)
                {
                    return client.Find(filter).FirstOrDefault<TEntity>();
                }

                //指定查询字段
                var fieldList = new List<ProjectionDefinition<TEntity>>();
                for (int i = 0; i < field.Length; i++)
                {
                    fieldList.Add(Builders<TEntity>.Projection.Include(field[i].ToString()));
                }
                var projection = Builders<TEntity>.Projection.Combine(fieldList);
                fieldList?.Clear();
                return client.Find(filter).Project<TEntity>(projection).FirstOrDefault<TEntity>();
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 根据条件获取一条数据
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="whereExpression">条件</param>
        /// <returns></returns>
        public TEntity Get(string name, Expression<Func<TEntity, bool>> whereExpression)
        {
            var client = db.GetCollection<TEntity>(name);
            var entity=client.Find(whereExpression).FirstOrDefault();
            return entity;
        }

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public async Task<TEntity> GetAsync(string name,Expression<Func<TEntity, bool>> whereExpression)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                var entity= (await client.FindAsync(whereExpression)).FirstOrDefaultAsync().Result;
                return entity;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 异步根据id查询一条数据
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="id">objectid</param>
        /// <param name="field">要查询的字段，不写时查询全部</param>
        /// <returns></returns>
        public async Task<TEntity> GetAsync(string name, string id, string[]? field = null)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                FilterDefinition<TEntity> filter = Builders<TEntity>.Filter.Eq("_id", new ObjectId(id));
                //不指定查询字段
                if (field == null || field.Length == 0)
                {
                    return await client.Find(filter).FirstOrDefaultAsync();
                }

                //指定查询字段
                var fieldList = new List<ProjectionDefinition<TEntity>>();
                for (int i = 0; i < field.Length; i++)
                {
                    fieldList.Add(Builders<TEntity>.Projection.Include(field[i].ToString()));
                }
                var projection = Builders<TEntity>.Projection.Combine(fieldList);
                fieldList?.Clear();
                return await client.Find(filter).Project<TEntity>(projection).FirstOrDefaultAsync();
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 查询集合
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="filter">查询条件</param>
        /// <param name="field">要查询的字段,不写时查询全部</param>
        /// <param name="sort">要排序的字段</param>
        /// <returns></returns>
        public List<TEntity> GetList(string name, FilterDefinition<TEntity> filter, string[]? field = null, SortDefinition<TEntity>? sort = null)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                //不指定查询字段
                if (field == null || field.Length == 0)
                {
                    if (sort == null) return client.Find(filter).ToList();
                    //进行排序
                    return client.Find(filter).Sort(sort).ToList();
                }

                //指定查询字段
                var fieldList = new List<ProjectionDefinition<TEntity>>();
                for (int i = 0; i < field.Length; i++)
                {
                    fieldList.Add(Builders<TEntity>.Projection.Include(field[i].ToString()));
                }
                var projection = Builders<TEntity>.Projection.Combine(fieldList);
                fieldList?.Clear();
                if (sort == null) return client.Find(filter).Project<TEntity>(projection).ToList();
                //排序查询
                return client.Find(filter).Sort(sort).Project<TEntity>(projection).ToList();
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public async Task<List<TEntity>> GetListAsync(string name, Expression<Func<TEntity, bool>> whereExpression)
        {
            try
            {
                var list = new List<TEntity>();
                if (!await ExistsAsync(name)) return list;
                var client = db.GetCollection<TEntity>(name);
                list = (await client.FindAsync(whereExpression)).ToListAsync().Result;
                return list;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 根据条件获取条数
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="whereExpression">条件</param>
        /// <returns></returns>
        public async Task<long> CountAsync(string name, Expression<Func<TEntity, bool>> whereExpression)
        {
            try
            {
                long count = 0;
                if (!await ExistsAsync(name)) return 0;
                var client = db.GetCollection<TEntity>(name);
                count = await client.CountAsync(whereExpression);
                return count;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 异步查询集合
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="filter">查询条件</param>
        /// <param name="field">要查询的字段,不写时查询全部</param>
        /// <param name="sort">要排序的字段</param>
        /// <returns></returns>
        public async Task<List<TEntity>> GetListAsync(string name, FilterDefinition<TEntity> filter, string[]? field = null, SortDefinition<TEntity>? sort = null)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                //不指定查询字段
                if (field == null || field.Length == 0)
                {
                    if (sort == null) return await client.Find(filter).ToListAsync();
                    return await client.Find(filter).Sort(sort).ToListAsync();
                }

                //指定查询字段
                var fieldList = new List<ProjectionDefinition<TEntity>>();
                for (int i = 0; i < field.Length; i++)
                {
                    fieldList.Add(Builders<TEntity>.Projection.Include(field[i].ToString()));
                }
                var projection = Builders<TEntity>.Projection.Combine(fieldList);
                fieldList?.Clear();
                if (sort == null) return await client.Find(filter).Project<TEntity>(projection).ToListAsync();
                //排序查询
                return await client.Find(filter).Sort(sort).Project<TEntity>(projection).ToListAsync();
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 分页查询集合
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="filter">查询条件</param>
        /// <param name="pageIndex">页码，从1开始</param>
        /// <param name="pageSize">页数据量</param>
        /// <param name="count">总条数</param>
        /// <param name="field">要查询的字段,不写时查询全部</param>
        /// <param name="sort">要排序的字段</param>
        /// <returns></returns>
        public List<TEntity> GetList(string name, FilterDefinition<TEntity> filter, int pageIndex, int pageSize, out long count, string[]? field = null, SortDefinition<TEntity>? sort = null)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                count = client.CountDocuments(filter);
                if (pageIndex < 1 || pageSize < 1)
                {
                    return null;
                }
                //不指定查询字段
                if (field == null || field.Length == 0)
                {
                    if (sort == null) return client.Find(filter).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList();
                    //进行排序
                    return client.Find(filter).Sort(sort).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList();
                }

                //指定查询字段
                var fieldList = new List<ProjectionDefinition<TEntity>>();
                for (int i = 0; i < field.Length; i++)
                {
                    fieldList.Add(Builders<TEntity>.Projection.Include(field[i].ToString()));
                }
                var projection = Builders<TEntity>.Projection.Combine(fieldList);
                fieldList?.Clear();

                //不排序
                if (sort == null) return client.Find(filter).Project<TEntity>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList();

                //排序查询
                return client.Find(filter).Sort(sort).Project<TEntity>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList();

            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 异步分页查询集合
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="filter">查询条件</param>
        /// <param name="pageIndex">页码，从1开始</param>
        /// <param name="pageSize">页数据量</param>
        /// <param name="field">要查询的字段,不写时查询全部</param>
        /// <param name="sort">要排序的字段</param>
        /// <returns></returns>
        public async Task<List<TEntity>> GetListAsync(string name, FilterDefinition<TEntity> filter, int pageIndex, int pageSize, string[]? field = null, SortDefinition<TEntity>? sort = null)
        {
            try
            {
                var client = db.GetCollection<TEntity>(name);
                if (pageIndex < 1 || pageSize < 1)
                {
                    return null;
                }
                //不指定查询字段
                if (field == null || field.Length == 0)
                {
                    if (sort == null) return await client.Find(filter).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();
                    //进行排序
                    return await client.Find(filter).Sort(sort).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();
                }

                //指定查询字段
                var fieldList = new List<ProjectionDefinition<TEntity>>();
                for (int i = 0; i < field.Length; i++)
                {
                    fieldList.Add(Builders<TEntity>.Projection.Include(field[i].ToString()));
                }
                var projection = Builders<TEntity>.Projection.Combine(fieldList);
                fieldList?.Clear();

                //不排序
                if (sort == null) return await client.Find(filter).Project<TEntity>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();

                //排序查询
                return await client.Find(filter).Sort(sort).Project<TEntity>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();

            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 异步分页查询集合
        /// </summary>
        /// <param name="name">数据集</param>
        /// <param name="where">查询条件</param>
        /// <param name="pageIndex">页码，从1开始</param>
        /// <param name="pageSize">页数据量</param>
        /// <param name="field">要查询的字段,不写时查询全部</param>
        /// <param name="sort">要排序的字段</param>
        /// <returns>Item1.结果集 Item2.总条数 Item3.总页数</returns>
        public async Task<(List<TEntity>,int,int)> GetListAsync(string name, Expression<Func<TEntity, bool>> where,
            int pageIndex, int pageSize, string[]? field = null, SortDefinition<TEntity>? sort = null)
        {
            try
            {             
                List<TEntity> result=new List<TEntity>();int pageCount = 0;int totalCount = 0;
                if(!await ExistsAsync(name)) return (result, totalCount, pageCount);
                var client = db.GetCollection<TEntity>(name);
                if (pageIndex < 1 || pageSize < 1) return (result, totalCount, pageCount);

                totalCount = (int)await client.CountAsync(where);
                //不指定查询字段
                if (field == null || field.Length == 0)
                {
                    if (sort==null)
                        result = await client.Find(where).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();
                    //进行排序
                    else 
                        result= await client.Find(where).Sort(sort).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();
                }
                else
                {
                    //指定查询字段
                    var fieldList = new List<ProjectionDefinition<TEntity>>();
                    for (int i = 0; i < field.Length; i++)
                    {
                        fieldList.Add(Builders<TEntity>.Projection.Include(field[i].ToString()));
                    }
                    var projection = Builders<TEntity>.Projection.Combine(fieldList);
                    fieldList?.Clear();

                    //不排序
                    if (sort==null) 
                        result= await client.Find(where).Project<TEntity>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();

                    //排序查询
                    else
                        result = await client.Find(where).Sort(sort).Project<TEntity>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();
                }
                pageCount = (int)Math.Ceiling(totalCount / (decimal)pageSize);
                return (result, totalCount, pageCount);
            }
            catch (Exception)
            {
                throw;
            }
        }


        /// <summary>  
        /// 初始化查询记录 主要当该查询条件为空时 会附加一个恒真的查询条件，防止空查询报错  
        /// </summary>  
        /// <param name="query">查询的条件</param>  
        /// <param name="id">ObjectId的键</param>
        /// <returns></returns>  
        private IMongoQuery InitQuery(IMongoQuery query,string id)
        {
            if (query == null)
            {
                //当查询为空时 附加恒真的条件 类似SQL：1=1的语法  
                query = Query.Exists(id);
            }
            return query;
        }

    }
}
